import {LGXEnums}  from "../common/sysenum";


import modifymulposgraphsvc from "./graphmodsvc/modifymulposgraphsvc";
import modifyarcposgraphsvc from "./graphmodsvc/modifyarcposgraphsvc";
import modifycircleposgraphsvc from "./graphmodsvc/modifycircleposgraphsvc";
import modifymoldgraphsvc from "./graphmodsvc/modifymoldgraphsvc";
import modifyimagegraphsvc from "./graphmodsvc/modifyimagegraphsvc";
import dragrotatesvc from "./graphmodsvc/dragrotatesvc";
import modifytextsvc from "./graphmodsvc/modifytextsvc";
import modifycylindersvc from "./graphmodsvc/modifycylindersvc";
import modifycubesvc from "./graphmodsvc/modifycubesvc";
import modifysperect from "./graphmodsvc/modifysperect";
import modifyspepolygon from "./graphmodsvc/modifyspepolygon";

import LGXCom from "../common/common.js";
import utilfuncs from "../common/tools/utilfuncs";
var funcs = utilfuncs.UtilFuncs;

var GraphModifySvc = {}

GraphModifySvc.modify = function (controlGraph, graphList, offsetPtINWorld, mapscale, scaling) {
    console.log("GraphModifySvc.modify");
    let succes = false;
    let offsetPtIN = {x:0,y:0};

    // let localMtx = controlGraph.getLocalMatrix();
    // let orinPt = controlGraph.getLocalOrigin();
    // let trPtWorld = {x:0,y:0};
    // trPtWorld.x = orinPt.x + offsetPtINWorld.x;
    // trPtWorld.y = orinPt.y + offsetPtINWorld.y;
    // let invertMtx = localMtx.Inverse();
    // let transPtInLocal = invertMtx.MultT({ x: trPtWorld.x, y: trPtWorld.y, z: 0 });//求相对于控制图形局部坐标系的局部坐标  
    // offsetPtIN.x = transPtInLocal.x;
    // offsetPtIN.y = transPtInLocal.y;

    offsetPtIN.x = offsetPtINWorld.x;
    offsetPtIN.y = offsetPtINWorld.y;

    let x = offsetPtIN.x;
    let y = offsetPtIN.y;
    let validOffsetPt = { x, y };
    let offsetPtRefDir = { x, y };//考虑了拖动方向得偏移

    let dragKind = controlGraph.getSelKind();

    //相对于修改矩形框特征中心点的拖动方向向量，世界坐标系
    let transdirVector = new LGXCom.LGXVector();
    var ctrlFeaturePtlst = controlGraph.getScopeVertexPtLst(scaling);
    let localOrgPt = ctrlFeaturePtlst[LGXEnums.LGXModGraphKind.Drag_center - LGXEnums.LGXModGraphKind.CommonStSelKind - 1];
    let localDragPt = ctrlFeaturePtlst[dragKind - LGXEnums.LGXModGraphKind.CommonStSelKind - 1];

    switch (dragKind) {
        case LGXEnums.LGXModGraphKind.Drag_leftTop:
        case LGXEnums.LGXModGraphKind.Drag_rightTop:
        case LGXEnums.LGXModGraphKind.Drag_RightBottom:
        case LGXEnums.LGXModGraphKind.Drag_leftBottom:
        case LGXEnums.LGXModGraphKind.Drag_TopMid:
        case LGXEnums.LGXModGraphKind.Drag_RightMid:
        case LGXEnums.LGXModGraphKind.Drag_BottomMid:
        case LGXEnums.LGXModGraphKind.Drag_LeftMid:
            {
                // if (dragKind == LGXEnums.LGXModGraphKind.Drag_LeftMid
                //     || dragKind == LGXEnums.LGXModGraphKind.Drag_RightMid) {
                //     offsetPtRefDir.y = 0;
                // }
                // else if (dragKind == LGXEnums.LGXModGraphKind.Drag_TopMid
                //     || dragKind == LGXEnums.LGXModGraphKind.Drag_BottomMid) {
                //     offsetPtRefDir.x = 0;
                // }
                let invertDir = false;
                let transLen = Math.sqrt(offsetPtRefDir.x * offsetPtRefDir.x + offsetPtRefDir.y * offsetPtRefDir.y);
                transdirVector.setBy2Pt(localOrgPt, localDragPt);

                let preDis = funcs.distancePoint(localOrgPt, localDragPt, 1);
                x = localDragPt.x + offsetPtRefDir.x;
                y = localDragPt.y + offsetPtRefDir.y;
                let localDragToDstPt = { x, y };
                let nextDis = funcs.distancePoint(localOrgPt, localDragToDstPt, 1);
                if (nextDis < preDis) {
                    invertDir = true;
                    transdirVector.invert();
                }

                let transAngle_degree = transdirVector.angleFrmXAxisPositiveDir();
                let tansAngle_Rad = funcs.degree2Radian(transAngle_degree);
                validOffsetPt.x = 10;
                validOffsetPt.y = 0;
                validOffsetPt.x = transLen * Math.cos(tansAngle_Rad);
                validOffsetPt.y = transLen * Math.sin(tansAngle_Rad);
                this.drag2Modify(controlGraph, graphList, validOffsetPt, transdirVector, invertDir, mapscale);
                succes = true;
            }
            break;

        case LGXEnums.LGXModGraphKind.Drag_center:
            this.translate(controlGraph, graphList, validOffsetPt, mapscale);
            succes = true;
            break;

        case LGXEnums.LGXModGraphKind.Drag_rotHand:
            succes = dragrotatesvc.DragRotateSvc.dragRotate(controlGraph, graphList, localOrgPt, localDragPt, offsetPtIN, mapscale);
            break;
    }
    ctrlFeaturePtlst.length = 0;
    return succes;
}

GraphModifySvc.translate = function (controlGraph, graphList, offsetPt, mapscale) {
    let list = new Array();
    let lineLst = [];
    graphList.forEach(p => {
        if (list.indexOf(p) == -1) {
            list.push(p);
        }

        if (p.m_graphType == LGXEnums.LGXGraphType.LineGraph_type && lineLst.indexOf(p) == -1) {
            lineLst.push(p);
        }
    });
    if (list.indexOf(controlGraph) == -1) {
        list.push(controlGraph);
    }
    list.forEach(p => {
        p.translate(offsetPt, mapscale, true, lineLst);
        p.calScope(mapscale);
    });
    list.length = 0;
}


GraphModifySvc.drag2Modify = function (controlGraph, graphList, offsetPt, transdir, invertDir, mapscale) {
    //向量旋转公式：
    //（x0 + i*y0）(cos(thata)+i*sin(theta))
    //x = x0*cos(theta) - y0*sin(theta)
    //y = y0*cos(thata) + x0*sin(theta)
    let scopeRect = controlGraph.getZone();
    let scopeCnt = controlGraph.getLocalOrigin();// scopeRect.getCnt();//局部坐标系原点相对于世界坐标系的位置
    let x = scopeCnt.x;
    let y = scopeCnt.y;
    let newScopeCnt = { x, y };

    let graphRadAngle = controlGraph.getRadAngle();//destGraph图形相对于世界坐标系的旋转角度，弧度值
    newScopeCnt.x += offsetPt.x * 0.5;
    newScopeCnt.y += offsetPt.y * 0.5;

    //offsetPt 是相对于世界坐标系的偏移值，要把相对于世界坐标系的transdir向量投影到controlGraph的局部坐标系
    let localtransdirVector = new LGXCom.LGXVector();
    localtransdirVector.m = transdir.m * Math.cos(graphRadAngle) + transdir.n * Math.sin(graphRadAngle);
    localtransdirVector.n = transdir.n * Math.cos(graphRadAngle) - transdir.m * Math.sin(graphRadAngle);

    let transLen = Math.sqrt(offsetPt.x * offsetPt.x + offsetPt.y * offsetPt.y);
    let expandPara = 1;
    if (invertDir) {
        expandPara = -1;
    }
    let newWid = transLen * Math.abs(localtransdirVector.m) * expandPara + scopeRect.width();
    let newhgt = transLen * Math.abs(localtransdirVector.n) * expandPara + scopeRect.height();
    let scalex = newWid / scopeRect.width();
    let scaley = newhgt / scopeRect.height();
    let scale = { scalex, scaley };
    console.log("sx=" + scalex + "  sy=" + scaley);

    let contrlGraphSetFlag = true;
    let destGraphNewTransform = null;
    for (let i = 0; i < graphList.length; i++) {
        let destGraph = graphList[i];
        if (destGraph == controlGraph && graphList.length > 1) {
            contrlGraphSetFlag = false;
            continue;
        }
        let svc = this.getChildModifSvc(destGraph);
        if (svc) {
            destGraphNewTransform = this.getDstGraphTransformMtx(controlGraph, destGraph, newScopeCnt, scale);
            svc.drag2Modify(destGraph, destGraphNewTransform);
            destGraph.drag2ModifyGradientInfo(destGraphNewTransform);
        }
        destGraph.calScope(mapscale);
    }

    if (!contrlGraphSetFlag) {
        let svc = this.getChildModifSvc(controlGraph);
        if (svc) {
            let controlGraphNewTransform = this.getDstGraphTransformMtx(controlGraph, controlGraph, newScopeCnt, scale);
            svc.drag2Modify(controlGraph, controlGraphNewTransform);
            this.drag2ModifyNodes(graphList, controlGraphNewTransform);
        }
    }
    else if (destGraphNewTransform) {
        this.drag2ModifyNodes(graphList, destGraphNewTransform);
    }
    controlGraph.calScope(mapscale);
}

GraphModifySvc.drag2ModifyNodes = function (graphList, newTransform) {
    let nodeList = [];
    graphList.forEach(graph => {
        let topoRes = graph.getTopoRes();
        if (topoRes) {
            let graphConnNodeList = topoRes.getConnNodeList();
            graphConnNodeList.forEach(node => {
                if (node && nodeList.indexOf(node) == -1) {
                    nodeList.push(node);
                }
            });
        }
    });

    for (let i = 0; i < nodeList.length; i++) {
        let node = nodeList[i];
        let preNodePt = node.getPos();
        let PtInCtrlLocal = newTransform.destInverseMtx.MultT({ x: preNodePt.x, y: preNodePt.y, z: 0 });
        let newWolrdPt = newTransform.newDestMtx.MultT(PtInCtrlLocal);
        node.translate2DestPt(newWolrdPt,graphList);
    }
}

GraphModifySvc.getChildModifSvc = function (destGraph) {
    var svc = null;
    if (destGraph.m_graphType == LGXEnums.LGXGraphType.MoldGraph_type) {
        svc = modifymoldgraphsvc.ModifyMoldGraphSvc;
    }
    else if (destGraph.m_graphType == LGXEnums.LGXGraphType.CircleGraph_type
        ||destGraph.m_graphType == LGXEnums.LGXGraphType.EllipseGraph_type) {
        svc = modifycircleposgraphsvc.ModifyCirclePosGraphSvc;
    }
    else if (destGraph.m_graphType == LGXEnums.LGXGraphType.ArcGraph_type) {
        svc = modifyarcposgraphsvc.ModifyArcPosGraphSvc;
    }
    else if (destGraph.m_graphType == LGXEnums.LGXGraphType.ImageGraph_type) {
        svc = modifyimagegraphsvc.ModifyImageGraphSvc;
    }
    else if (destGraph.m_graphType == LGXEnums.LGXGraphType.TextGraph_type) {
        svc = modifytextsvc.ModifyTextGraphSvc;
    }
    else if (destGraph.m_graphType == LGXEnums.LGXGraphType.Cylinder_type) {
        svc = modifycylindersvc.ModifyCylinderSvc;
    }
    else if (destGraph.m_graphType == LGXEnums.LGXGraphType.Cube_type) {
        svc = modifycubesvc.ModifyCubeSvc;
    }
    else if (destGraph.m_graphType == LGXEnums.LGXGraphType.SpecialRect_type
        || destGraph.m_graphType == LGXEnums.LGXGraphType.XMindTheme_type) {
        svc = modifysperect.ModifySpeRectSvc;
    }
    else if (destGraph.m_graphType == LGXEnums.LGXGraphType.MultiStar_type
        || destGraph.m_graphType == LGXEnums.LGXGraphType.RegularPolygon_type) {
        svc = modifyspepolygon.ModifySpePolygonSvc;
    }
    else if (destGraph.getPosType() == LGXEnums.LGXPosMode.multiPt_Mode) {
        svc = modifymulposgraphsvc.ModifyMulPosGraphSvc;
    }

    return svc;
}

GraphModifySvc.getDstGraphTransformMtx = function (controlGraph, destGraph, newCtrlScopeCnt, scale) {
    let ctlMtx = controlGraph.getLocalMatrix();
    let ctlInverseMtx = ctlMtx.Inverse();

    let newCtlMtx = controlGraph.getLocalMatrix();
    newCtlMtx.SetS({ x: scale.scalex, y: scale.scaley, z: 1 });
    newCtlMtx.SetT({ x: newCtrlScopeCnt.x, y: newCtrlScopeCnt.y, z: 0 });

    let curentGraphPreMtx = destGraph.getLocalMatrix();
    let curentGraphPreMtxOrgPt = curentGraphPreMtx.GetT();//当前被修改图形局部坐标系原点
    let x = curentGraphPreMtxOrgPt.x;
    let y = curentGraphPreMtxOrgPt.y;
    let PtInCtrlLocal = ctlInverseMtx.MultT({ x: x, y: y, z: 0 });
    let curentGraphNextMtxOrgPt = newCtlMtx.MultT(PtInCtrlLocal);//当前被修改图形局部坐标系原点相对于控制图形局部坐标系的坐标

    let XCurentGraphPreMtxAxis = curentGraphPreMtx.GetRow(0);//当前图局部坐标系X轴相对于世界坐标系的向量
    x = curentGraphPreMtxOrgPt.x + XCurentGraphPreMtxAxis.x;
    y = curentGraphPreMtxOrgPt.y + XCurentGraphPreMtxAxis.y;
    PtInCtrlLocal = ctlInverseMtx.MultT({ x: x, y: y, z: 0 });
    let XCurentGraphNextMtxAxis = newCtlMtx.MultT(PtInCtrlLocal);//当前被修改图形局部坐标系X轴顶点（1，0，0）相对于控制图形局部坐标系的坐标

    let YCurentGraphPreMtxAxis = curentGraphPreMtx.GetRow(1);
    x = curentGraphPreMtxOrgPt.x + YCurentGraphPreMtxAxis.x;
    y = curentGraphPreMtxOrgPt.y + YCurentGraphPreMtxAxis.y;
    PtInCtrlLocal = ctlInverseMtx.MultT({ x: x, y: y, z: 0 });
    let YCurentGraphNextMtxAxis = newCtlMtx.MultT(PtInCtrlLocal);

    let ZCurentGraphPreMtxAxis = curentGraphPreMtx.GetRow(2);
    x = curentGraphPreMtxOrgPt.x + ZCurentGraphPreMtxAxis.x;
    y = curentGraphPreMtxOrgPt.y + ZCurentGraphPreMtxAxis.y;
    PtInCtrlLocal = ctlInverseMtx.MultT({ x: x, y: y, z: 0 });
    let ZCurentGraphNextMtxAxis = newCtlMtx.MultT(PtInCtrlLocal);

    let destScaleX = funcs.distancePoint(curentGraphNextMtxOrgPt, XCurentGraphNextMtxAxis, 1);
    let destScaleY = funcs.distancePoint(curentGraphNextMtxOrgPt, YCurentGraphNextMtxAxis, 1);

    let newDestMtx = destGraph.getLocalMatrix();
    newDestMtx.SetS({ x: destScaleX, y: destScaleY, z: 1 });
    newDestMtx.SetT({ x: curentGraphNextMtxOrgPt.x, y: curentGraphNextMtxOrgPt.y, z: 0 });

    let destInverseMtx = curentGraphPreMtx.Inverse();
    return { newDestMtx, destInverseMtx };
}

export { GraphModifySvc }